/*
 *  CSE 40166, Computer Graphics, Fall 2013
 *  Assignment 4, Part 2
 *
 *  File: textureReader.cpp
 *
 *  Kevin Sonnen
 *
 *  Description: Contains implementation for class with functionality for 
 *  registering a texture and reading in a PPM.
 *
 */
 
#include "textureReader.h"

////////////////////////////////////////////
// textureReader Member Functions
////////////////////////////////////////////

//
// bool registerOpenGLTexture(unsigned char *textureData, 
//						   unsigned int texWidth, unsigned int texHeight, 
//						   GLuint &textureHandle)
//
// Takes as parameters the raw image data, image dimensions, and
// the texture handle.  It then creates a texture handle, sets up the texture
// parameters, and finally registers the texture with OpenGL and the GPU
//
bool 
textureReader::registerOpenGLTexture(unsigned char *textureData, 
						   unsigned int texWidth, unsigned int texHeight, 
						   GLuint &textureHandle) {
    if(textureData == 0) {
        fprintf(stderr,"Cannot register texture; no data specified.");
        return false;
    }
	
	//glGenTextures( 1, &textureHandle );
	glBindTexture( GL_TEXTURE_2D, textureHandle );

	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	// GL_MODULATE or GL_DECAL
	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);	// GL_MODULATE or GL_DECAL
	
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  // a MIN Filter MUST BE SET
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);	// GL_REPEAT or GL_CLAMP
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		
    GLenum errCode;
    const GLubyte *errString;
	
    if ((errCode = glGetError()) != GL_NO_ERROR) {
        errString = gluErrorString(errCode);
        fprintf(stderr,"Cannot register texture; OpenGL error: %s.", errString);
        return false;
    } 
	
    glTexImage2D( GL_TEXTURE_2D,	// specifying a 2D texture
				 0,					// level of the texture map - used for mipmapping
				 GL_RGB,			// internal format of image data
				 texWidth,			// texture width
				 texHeight,			// texture height
				 0,					// border width - used for filtering
				 GL_RGB,			// type of texels to use
				 GL_UNSIGNED_BYTE,	// how is the data stored in array
				 textureData		// pointer to array of image data
				 );
    return true;
}

//
// bool readPPM(std::string filename, int &imageWidth, int &imageHeight, unsigned char* &imageData)
//
// Reads a PPM with the given filename. Sets imageWidth, imageHeight, and character array
// imageData. Reads either an ASCII PPM (P3) or a binary PPM (P6)
//
bool 
textureReader::readPPM(std::string filename, int &imageWidth, int &imageHeight, unsigned char* &imageData) {
    FILE *fp = fopen(filename.c_str(), "r");
    if (fp) {
		int temp, maxValue;
		fscanf(fp, "P%d", &temp);
		if (temp == 6) {
			//got the file header right...
			fscanf(fp, "%d", &imageWidth);
			fscanf(fp, "%d", &imageHeight);
			fscanf(fp, "%d ", &maxValue);
	
			//now that we know how big it is, allocate the buffer...
			imageData = new unsigned char[imageWidth*imageHeight*3];
			if(!imageData) {
			fprintf(stderr, "Error: couldn't allocate image memory. Dimensions: %d x %d.\n", imageWidth, imageHeight);
			fclose(fp);
			return false;
			}
	
			fread(imageData,imageWidth*imageHeight*3,sizeof(unsigned char),fp);
		} else if (temp == 3) {
			//got the file header right...
			fscanf(fp, "%d", &imageWidth);
			fscanf(fp, "%d", &imageHeight);
			fscanf(fp, "%d", &maxValue);
	
			//now that we know how big it is, allocate the buffer...
			imageData = new unsigned char[imageWidth*imageHeight*3];
			if(!imageData) {
			fprintf(stderr, "Error: couldn't allocate image memory. Dimensions: %d x %d.\n", imageWidth, imageHeight);
			fclose(fp);
			return false;
			}
	
			//and read the data in.
			for(int j = 0; j < imageHeight; j++) {
			for(int i = 0; i < imageWidth; i++) {
				int r, g, b;
				fscanf(fp, "%d", &r);
				fscanf(fp, "%d", &g);
				fscanf(fp, "%d", &b);
			
				imageData[(j*imageWidth+i)*3+0] = r;
				imageData[(j*imageWidth+i)*3+1] = g;
				imageData[(j*imageWidth+i)*3+2] = b;
			}
			}
		} else {
		fprintf(stderr, "Error: PPM file is not of correct format! (Must be P3 or P6, is P%d.)\n", temp);
		    fclose(fp);
		    return false;
		}
		fclose(fp);
		return true;
	} else {
		return false;
	}
}
